Skip to content

Add "Drag And Drop To Frame" keyword for cross-frame drag-and-drop#1953

Open
b-vamsipunnam wants to merge 2 commits intorobotframework:masterfrom
b-vamsipunnam:feature/drag-and-drop-to-frame
Open

Add "Drag And Drop To Frame" keyword for cross-frame drag-and-drop#1953
b-vamsipunnam wants to merge 2 commits intorobotframework:masterfrom
b-vamsipunnam:feature/drag-and-drop-to-frame

Conversation

@b-vamsipunnam
Copy link
Copy Markdown
Contributor

@b-vamsipunnam b-vamsipunnam commented Dec 14, 2025

Summary

This PR adds a new keyword Drag And Drop To Frame that reliably supports dragging an element from the main document into a target element inside an iframe.

Motivation

While automating post-deployment tasks in a Salesforce Service Cloud setup flow, I encountered a limitation where drag-and-drop interactions failed when the drop target resided inside an iframe. The existing keywords could not handle this scenario because the WebDriver action chain loses context when switching into an iframe mid-action.

Real-world scenario: Salesforce Service Cloud application

  • Login → Setup → All Sites → Builder → Select Dashboard → Drag and drop a component into the target section (inside an iframe) → Publish → Confirm publish.
  • The existing Drag And Drop keywords failed because the target is inside an iframe.

This limitation aligns with

By introducing this keyword, the drag-and-drop flow can now be reliably automated end-to-end.

Changes:

  • Added implementation in src/SeleniumLibrary/keywords/element.py
  • Added acceptance tests in atest/acceptance/keywords/draganddropframe.robot
  • Added test HTML page atest/resources/html/frames/draganddrop.html
  • Updated unit test keyword count in utest/test/api/test_plugins.py

All acceptance tests pass locally, including the new cross-frame scenarios.

All acceptance tests pass locally (including new ones).

This is a non-trivial enhancement — please add the acknowledge label to #120 for release notes credit. Thank you!

@b-vamsipunnam b-vamsipunnam force-pushed the feature/drag-and-drop-to-frame branch from 91af1a0 to d283eb4 Compare December 20, 2025 21:16
@emanlove emanlove self-assigned this Dec 20, 2025
@b-vamsipunnam b-vamsipunnam changed the title Feature: Add New keyword Drag And Drop To Frame Add New keyword "Drag And Drop To Frame" Mar 30, 2026
@b-vamsipunnam b-vamsipunnam force-pushed the feature/drag-and-drop-to-frame branch from d283eb4 to bf869a0 Compare April 11, 2026 16:56
@b-vamsipunnam b-vamsipunnam changed the title Add New keyword "Drag And Drop To Frame" Add "Drag And Drop To Frame" keyword for cross-frame drag-and-drop Apr 11, 2026
@b-vamsipunnam
Copy link
Copy Markdown
Contributor Author

Hi @emanlove ,
I’ve updated the PR to align with the project’s keyword signature to use the new Locator type alias, and the PR is now scoped to:

  • The new Drag And Drop To Frame keyword implementation
  • Then updated acceptance tests

All tests are now passing in GitHub Actions. Please take another look when you have a chance. Thanks!

Copy link
Copy Markdown
Member

@yuriverweij yuriverweij left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this PR! it looks very promising, but there are a few things that need to be resolved.

  • There is a bug in the try/except which can cause the mouse button to stay down.
  • The test fixture (html file) has some problems which can give false positives
  • Suggestion: the keyword can be made a bit more generic allowing dragging from frame to frame or default context to frame. (in this case the Note can be removed from the docstring)
  • Suggestion: add the following to the docstring/description After this keyword runs, the browser context is always default content, regardless of the context before the call.

target_element = self.find_element(target)

action = ActionChains(self.driver, duration=self.ctx.action_chain_delay)
action.move_to_element(target_element).release().perform()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the find_element() for frame or target raises an error, the mouse button is still held down. The finally switches context back but never releases. The next action in the suite inherits a held mouse button.

Standard Drag And Drop Fails When Target Is Inside Frame
[Documentation] Verifies that the standard Drag And Drop keyword cannot complete this cross-frame scenario.
Wait Until Page Contains Element id=source timeout=10s
Run Keyword And Expect Error * Drag And Drop id=source id=target
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not wildcard the error that is expected. This can cause the test to "pass" when any error occurs.

Drag And Drop To Frame Fails With Invalid Frame
[Documentation] Verifies that the keyword fails when the frame locator is invalid.
Wait Until Page Contains Element id=source timeout=10s
Run Keyword And Expect Error * Drag And Drop To Frame
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not wildcard the error that is expected. This can cause the test to "pass" when any error occurs.
Element with locator 'id=missingFrame' not found

Drag And Drop To Frame Fails With Invalid Target
[Documentation] Verifies that the keyword fails when the target element is not found inside the iframe.
Wait Until Page Contains Element id=source timeout=10s
Run Keyword And Expect Error * Drag And Drop To Frame
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not wildcard the error that is expected. This can cause the test to "pass" when any error occurs.
Element with locator 'id=missingTarget' not found


@keyword('Drag And Drop To Frame')
def drag_and_drop_to_frame(
self, locator: Locator, target: Locator, frame: Locator,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to make the keyword more generic it might be worth changing some parts:

def drag_and_drop_across_frames( self, locator: Locator, target: Locator, target_frame: Locator, source_frame: Optional[Locator] = None,

  • locator: Locator of the source element to drag.
  • target: Locator of the drop target.
  • target_frame: Locator of the iframe containing the target.
  • source_frame: Locator of the iframe containing the source, or None if the source is in the default content.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test fixture does not seem to work as intended.
Right now:
When clicking on the "Drag Me!" box, and performing a mouseup (releasing the mouse button anywhere) will trigger "Dropped Successfully", regardless of actually moving/draggint the box.

The test would pass even if move_to_element(target_element) did nothing.
The test would pass even if the frame switch silently failed (as long as a mouseup fires somewhere).
The test would pass if you replaced the whole keyword body with click_and_hold().release() on the source.

The fixture needs to validate that the drop actually lands on the target inside the frame, e.g. using real HTML5 DnD events or at least checking the mouseup coordinates hit the target's bounding box. As written, these tests give false confidence

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants